/************************************************************************
 * The code is owned by mainframer.cn and Shang Tao
 * Without aproval of mainframer.cn and Shang Tao, removing the copyright
 * infomation is regarded as invassion of proprietary copyright
 ***********************************************************************/
package com.mr.qa.dao.impl;

import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.Session;

import com.mr.qa.GlobalConfigs;
import com.mr.qa.bo.User;
import com.mr.qa.bo.UserLevel;
import com.mr.qa.bo.UserMoney;
import com.mr.qa.bo.UserMoneySpendHistory;
import com.mr.qa.bo.UserScore;
import com.mr.qa.bo.UserScoreHistory;
import com.mr.qa.util.HibernateSessionFactory;

/**
 * Data access object (DAO) for domain model
 * @author MyEclipse - Hibernate Tools
 */
public class BaseHibernateDAO implements IBaseHibernateDAO,UserScoreHistoryConstants
{
        private static final Log log = LogFactory.getLog(BaseHibernateDAO.class); 
        
        
        
	private Integer pageNo = new Integer(1);//defaults to 1
	
	private Integer recordCount = new Integer(10);//defaults to 10
	
        //to filter questions
        private String userType = null;
        
        private boolean cacheable = false;
        
        public String getUserType()
        {
            return userType;
        }

        public void setUserType(String userType)
        {
            this.userType = userType;
        }
        
        
	public void setPage(Integer pageNo, Integer recordCount)
        {
		this.pageNo = pageNo;
		this.recordCount = recordCount;
	}
	
	public Session getSession() 
        {
		return HibernateSessionFactory.getSession();
	}

	public Integer getPageNo() 
        {
		return pageNo;
	}

	public Integer getRecordCount() 
        {
		return recordCount;
	}

        /**
         * save a ScoreHistory, update user score
         */
	public void addScoreHistory(Integer userId,Integer resourceId, String resourceName,String resourceType,String description) throws Exception
        {
            try
            {
                User user = (User)this.getSession().get("com.mr.qa.bo.User",userId);
                addScoreHistory(user,resourceId,resourceName, resourceType,description);
            }
            catch(Exception e)
            {
                log.error(e);
                throw e;
            }
        }
	
    /**
     * @param user User whom the resource belongs to
     * save a ScoreHistory, update user score, update the counts of user's questions and answers
     */
    public void addScoreHistory(User user,Integer resourceId, String resourceName,String resourceType,String description) throws Exception
    {
        try
        {
            UserScoreHistory ush = new UserScoreHistory();
            ush.setResourceId(resourceId);
            ush.setResourceName(resourceName);
            if(resourceType != null && resourceType.length() > 30)
                resourceType = resourceType.substring(0,30);
            ush.setType(resourceType);
            ush.setDate(new Date());
            if(description != null && description.length() > 50)
                description = description.substring(0,50);
            ush.setDescription(description);
            ush.setUser(user);
            
           if("register".equals(resourceType))
            {
                ush.setScore(10);
            }
            /*else if("login".equals(resourceType))
            {
                ush.setScore(1);
            }*/
            else if("newquestion".equals(resourceType))
            {
                ush.setScore(5);
                //update the count of user's questions
                Integer answerCount = user.getAnswersCount();
                if(answerCount != null)
                    user.setQuestionsCount(user.getQuestionsCount()+1);
                else
                    user.setQuestionsCount(1);
            }
            else if("recommend".equals(resourceType))
            {
                ush.setScore(20);
            }
            else if("unrecommend".equals(resourceType))
            {
                ush.setScore(-20);
            }
            else if(USER_SCORE_HISTORY_ADD_ANSWER.equals(resourceType))
            {
                ush.setScore(2);
                Integer answerCount = user.getAnswersCount();
                //update the count of user's answers
                if(answerCount != null)
                    user.setAnswersCount(user.getAnswersCount()+1);
                else
                    user.setAnswersCount(1);
            }
            /*else if("vote".equals(resourceType))
            {
                ush.setScore(1);
            }*/
            else if(USER_SCORE_HISTORY_DELETE_QUESTION_BY_ADMIN.equals(resourceType))
            {
                ush.setScore(-5);
                //update the count of user's questions
                user.setQuestionsCount(user.getQuestionsCount()-1);
            }
            else if(USER_SCORE_HISTORY_DELETE_QUESTION_BY_SELF.equals(resourceType))
            {
                ush.setScore(-5);
                //update the count of user's questions
                user.setQuestionsCount(user.getQuestionsCount()-1);
            }
            else if(USER_SCORE_HISTORY_DELETE_ANSWER_BY_ADMIN.equals(resourceType))
            {
                ush.setScore(-2);
                //update the count of user's answers
                user.setAnswersCount(user.getAnswersCount()-1);
            }
            else if(USER_SCORE_HISTORY_DELETE_ANSWER_BY_SELF.equals(resourceType))
            {
                ush.setScore(-2);
                //update the count of user's answers
                user.setAnswersCount(user.getAnswersCount()-1);
            }
            else if(USER_SCORE_HISTORY_DELETE_ANSWER_BY_QUESTION.equals(resourceType))
            {
                ush.setScore(-2);//??
                //update the count of user's answers
                user.setAnswersCount(user.getAnswersCount()-1);
            }
            /*else if("deletecommentbyadmin".equals(resourceType))
            {
                ush.setScore(-2);
            }*/
            else if("uploadsharedfile".equals(resourceType))
            {
                ush.setScore(10);
            }
            else if(USER_SCORE_HISTORY_DELETE_SHARED_FILES.equals(resourceType))
            {
                ush.setScore(-10);
            }
            /*else if("downloadsharedfile".equals(resourceType))
            {
                ush.setScore(-5);
            }*/
            else if("addtosharedfileauthor".equals(resourceType))
            {
                ush.setScore(1);
            }/*else if(USER_SCORE_HISTORY_ADD_COMMENT_SHARED_FILES.equals(resourceType))
            {
                ush.setScore(2);
            }*/
            
            UserScore us = user.getUserScore();
            
            if(us == null)
            {
                us = new UserScore();
                //us.setTitle("New Member");
                us.setTotalScore(ush.getScore());
                us.setMrIaskUser(user);
                user.setUserScore(us);
                
            }
            else
            {
                us.setTotalScore(us.getTotalScore()+ush.getScore());
            }
            
            UserMoney um = user.getUserMoney();
            if(um == null){
            	um = new UserMoney();
            	um.setTotalMoney(ush.getScore());
            	um.setMrIaskUser(user);
            	user.setUserMoney(um);
            }else{
            	um.setTotalMoney(um.getTotalMoney() + ush.getScore());
            }
            //
            String updatedTitile = this.selectUserTitle(us.getTotalScore(),user.getGroup());
            us.setTitle(updatedTitile);
            this.getSession().save(ush);
            this.getSession().update(user);
        }
        catch(Exception e)
        {
            log.error(e);
            throw e;
        }
    }
    
    public void spendMoney(User user,Integer resourceId, String resourceName,String resourceType,String description) throws Exception{
    	spendMoney(user, resourceId, resourceName, resourceType, description, 0);
    }
    
    public void spendMoney(User user,Integer resourceId, String resourceName,String resourceType,String description, int money) throws Exception{
    	try {
			UserMoneySpendHistory umsh = new UserMoneySpendHistory();
			umsh.setResourceId(resourceId);
			umsh.setResourceName(resourceName);
			if (resourceType != null && resourceType.length() > 30)
				resourceType = resourceType.substring(0, 30);
			umsh.setType(resourceType);
			umsh.setDate(new Date());
			if (description != null && description.length() > 50)
				description = description.substring(0, 50);
			umsh.setDescription(description);
			umsh.setUser(user);

			if ("downloadSharedFile".equals(resourceType)) {
				umsh.setMoney(0 - GlobalConfigs.SHARED_FILE_MONEY);
			}
			else if ("autoWeeklyAward".equals(resourceType)) {
				umsh.setMoney(money);
			}else if("exchangeArticle".equals(resourceType)){
				umsh.setMoney(money);
			}else if("adminAward".equals(resourceType)){
				umsh.setMoney(money);
			}

			UserMoney um = user.getUserMoney();

			if (um == null) {
				um = new UserMoney();
				um.setTotalMoney(umsh.getMoney());
				um.setMrIaskUser(user);
				user.setUserMoney(um);
			} else {
				um.setTotalMoney(um.getTotalMoney() + umsh.getMoney());
			}
			//
			this.getSession().save(umsh);
			this.getSession().update(user);
		} catch (Exception e) {
			log.error(e);
			throw e;
		}
	}

    public String selectUserTitle(Integer userScore,String userGroup) 
    {
        String userTitle = "";    
        try
        {
            TreeMap ulds = GlobalConfigs.userLevelDefinitons;
            Set keys = ulds.keySet();
            String key = "";
            Integer startScore = 0;
            Integer endScore = 0;
            Iterator keyIte = keys.iterator();
            UserLevel ul = null;
            while(keyIte.hasNext())
            {
                key = (String)keyIte.next();
                //System.out.println("key="+key);
                ul = (UserLevel)ulds.get(key);
                //System.out.println("ul="+ul);
                if(key.indexOf(userGroup) >= 0)
                {
                    startScore = ul.getStartScore();
                    endScore = ul.getEndScore();
                    if(userScore >= startScore && userScore <= endScore)
                    {
                        userTitle = ul.getTitle();
                        break;
                    }
                }
            }
        }catch(Exception e)
        {
            System.out.println(">>>selectUserTitle:"+e);
        }
        
        return userTitle;
    }

    protected int countQuery(String queryString, HashMap parameters)
    {
        Query queryObject = getSession().createQuery(queryString);
        if(parameters != null && parameters.size() > 0)
        {
            //int parameterSize = parameters.size();
            int seqNo = 0;
            Set keys = parameters.keySet();
            Iterator keyIte = keys.iterator();
            while(keyIte.hasNext())
            {
                seqNo = ((Integer)keyIte.next()).intValue();
                queryObject.setParameter(seqNo,parameters.get(seqNo));
            }
        }
        if(queryObject.uniqueResult() != null){
        	long longCount = (Long)queryObject.uniqueResult();
        	return (int)longCount;
        }
        return 0;
    }

    protected java.util.List getQueryList(String queryString, HashMap parameters)
    {
        Query queryObject = getSession().createQuery(queryString);
        if(parameters != null && parameters.size() > 0)
        {
            //int parameterSize = parameters.size();
            int seqNo = 0;
            Set keys = parameters.keySet();
            Iterator keyIte = keys.iterator();
            while(keyIte.hasNext())
            {
                seqNo = ((Integer)keyIte.next()).intValue();
                queryObject.setParameter(seqNo,parameters.get(seqNo));
            }
        }
        if(this.getPageNo().intValue() > 0 && this.getRecordCount().intValue() > 0)
        {
            queryObject.setFirstResult((getPageNo().intValue() - 1) * getRecordCount().intValue());
            queryObject.setMaxResults(getRecordCount().intValue());
        }
        if(this.isCacheable())
        {
            queryObject.setCacheable(true);//2008.12.6
            //log.info("cache....");
        }
        List results = queryObject.list();
        return results;
    }

    public void setCacheable(boolean cacheable) {
        this.cacheable = cacheable;
    }

    public boolean isCacheable() {
        return cacheable;
    }
}
